package com.hibase.core.rule.service.ruleexecute.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hibase.common.exception.HibaseAssert;
import com.hibase.core.redis.util.RedisUtil;
import com.hibase.core.rule.config.DynamicDataSource;
import com.hibase.core.rule.constant.RuleFieldType;
import com.hibase.core.rule.constant.RuleStatus;
import com.hibase.core.rule.constant.RuleType;
import com.hibase.core.rule.entity.ruledatasource.RuleDataSource;
import com.hibase.core.rule.entity.ruledebug.RuleCallParamVO;
import com.hibase.core.rule.entity.ruledebug.RuleDebugParamVO;
import com.hibase.core.rule.entity.ruledebug.RuleDebugResultVO;
import com.hibase.core.rule.entity.ruledebug.RuleExecuteParamVO;
import com.hibase.core.rule.entity.rulemenu.RuleMenuContent;
import com.hibase.core.rule.entity.ruletable.RuleTable;
import com.hibase.core.rule.entity.ruletable.RuleTableField;
import com.hibase.core.rule.entity.ruletableversion.RuleTableVersion;
import com.hibase.core.rule.mapper.ruleexecute.RuleExecuteMapper;
import com.hibase.core.rule.service.ruledatasource.RuleDataSourceService;
import com.hibase.core.rule.service.ruleexecute.RuleExecuteService;
import com.hibase.core.rule.service.rulemenu.RuleMenuContentService;
import com.hibase.core.rule.service.ruletable.RuleTableFieldService;
import com.hibase.core.rule.service.ruletable.RuleTableService;
import com.hibase.core.rule.service.ruletableversion.RuleTableVersionService;
import com.hibase.core.rule.utils.HiBaseSqlUtils;
import com.hibase.core.rule.utils.HibaseRuleEngineUtils;
import com.hibase.core.rule.utils.RuleUtils;
import com.ql.util.express.DefaultContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 描述:
 * 规则debug实现类
 * <li>2022年1月28日-增加动态SQL的Map参数支持</li>
 *
 * @author li-wei-hua
 * @date 2020-03-19 14:03
 */
@Slf4j
@Service
public class RuleExecuteServiceImpl implements RuleExecuteService {
    @Autowired
    private RuleMenuContentService ruleMenuContentService;
    @Autowired
    private RuleExecuteMapper ruleExecuteMapper;
    @Autowired
    private HibaseRuleEngineUtils hibaseRuleEngineUtils;
    // 数据源相关
    @Autowired
    private RuleDataSourceService ruleDataSourceService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private RuleTableVersionService ruleTableVersionService;
    @Autowired
    private RuleTableFieldService ruleTableFieldService;
    @Autowired
    private RuleTableService ruleTableService;


    @Override
    public RuleDebugResultVO debug(RuleDebugParamVO paramVO) {
        // step 1. 查询规则, 判断是规则调试，还是数据源
        RuleMenuContent ruleMenuContent = getRuleMenuContent(paramVO.getId());

        // 返回对象
        RuleDebugResultVO result = new RuleDebugResultVO();

        if (ruleMenuContent.getType().equals(RuleType.RULE_TYPE_SOURCE.getName())) {
            // step 2. 数据源， 设置当前数据源， 执行sql 返回结果
            // 参数解析
            Object params = HiBaseSqlUtils.getSqlStatementParameters(ruleMenuContent.getContent(), paramVO.getData());
            result.setDebugLog(Collections.singletonList(HiBaseSqlUtils.disposeSqlLimit50(ruleMenuContent.getContent(), params)));
            result.setResult(this.executeSelectSqlDebug(ruleMenuContent.getDataSource(), ruleMenuContent.getContent(), params));

        } else if (ruleMenuContent.getType().equals(RuleType.RULE_TYPE_RULE.getName())) {
            // step 3. 规则， 执行规则语法， 返回执行结果.
            DefaultContext<String, Object> paramContext = new DefaultContext<>();
            // 参数解析
            if (StrUtil.isNotBlank(paramVO.getData())) {
                // 解析json
                paramContext.putAll(JSON.parseObject(paramVO.getData()).getInnerMap());
            }
            //result = hibaseRuleEngineUtils.executeRuleByDebug(ruleMenuContent,paramContext);
            try {
                result = hibaseRuleEngineUtils.executeRuleByDebug(ruleMenuContent, paramContext);
            } catch (Exception ex) {
                log.error(ex.getMessage());
                return result;
            }
        }
        return result;
    }

    @Deprecated
    @Override
    public Object executeRule(RuleExecuteParamVO paramVO) throws Exception {
        RuleMenuContent ruleMenuContent = ruleMenuContentService.getById(paramVO.getId());
        HibaseAssert.notNull(ruleMenuContent, "请选择记录");
        HibaseAssert.isTrue(ruleMenuContent.getType().equals(RuleType.RULE_TYPE_RULE.getName()), "请选择正确的规则");

        DefaultContext<String, Object> paramContext = new DefaultContext<>();
        // 参数解析
        if (StrUtil.isNotBlank(paramVO.getData())) {
            // 解析json
            paramContext.put("参数", JSON.parseObject(paramVO.getData()).getInnerMap());
            paramContext.putAll(JSON.parseObject(paramVO.getData()).getInnerMap());
        }

        return hibaseRuleEngineUtils.executeExpress(ruleMenuContent, paramContext);

    }

    @Override
    public Object executeRule(RuleMenuContent ruleMenuContent, Map<String, Object> map) throws Exception {
        HibaseAssert.notNull(ruleMenuContent, "规则不存在");
        HibaseAssert.isTrue(ruleMenuContent.getType().equals(RuleType.RULE_TYPE_RULE.getName()), "请选择正确的规则");
        DefaultContext<String, Object> paramContext = new DefaultContext<>();
        // 参数解析
        paramContext.putAll(map);
        return hibaseRuleEngineUtils.executeExpress(ruleMenuContent, paramContext);
    }

    @Override
    public List<Map<String, Object>> executeSelectSqlDebug(String dataSourceName, String sqlStr, Object... args) {
        // step 1. 查询数据库内的数据源配置
        RuleDataSource ruleDataSource = ruleDataSourceService.getOne(new QueryWrapper<RuleDataSource>().eq("poll_name", dataSourceName));
        HibaseAssert.notNull(ruleDataSource, "未找到数据源[{}],对应配置", dataSourceName);

        List<Map<String, Object>> maps = null;
        try {
            DruidDataSource druidDataSource = new DruidDataSource();
            druidDataSource.setUrl(ruleDataSource.getUrl());
            druidDataSource.setUsername(ruleDataSource.getUsername());
            // 解密
            //DES des = SecureUtil.des(CommConstant.SECURE_KEY.getBytes());
            druidDataSource.setPassword(ruleDataSource.getPassword());
            DynamicDataSource.dataSourcesMap.put(dataSourceName, druidDataSource);
            // 得到原数据源
            String source = DynamicDataSource.getDataSource();
            // 修改数据源
            DynamicDataSource.setDataSource(dataSourceName);
            //   此时数据源已切换到druidDataSource ，调用自己的业务方法即可。
            if (args[0] instanceof Map) {
                maps = ruleExecuteMapper.selectByMap(sqlStr, (Map<String, Object>) args[0]);
            } else {
                maps = ruleExecuteMapper.select(sqlStr, args);
            }

            //    maps = ruleExecuteMapper.selectDebug(sqlStr, args);
            // 还原数据源
            DynamicDataSource.setDataSource(source);
            DynamicDataSource.clear();

        } catch (Exception e) {
            e.printStackTrace();
            log.info("【数据源错误】 请检查sql 语句 或数据源配置 {}", e.getMessage());
            HibaseAssert.isTrue(false, "【数据源错误】 请检查sql 语句 或数据源配置 {}", e.getMessage());
        }

        return maps;
    }


    @Override
    public List<Map<String, Object>> executeSelectSql(String dataSourceName, String sqlStr, Object... args) {

        // step 1. 查询数据库内的数据源配置
        RuleDataSource ruleDataSource = ruleDataSourceService.getOne(new QueryWrapper<RuleDataSource>().eq("poll_name", dataSourceName));
        HibaseAssert.notNull(ruleDataSource, "未找到数据源[{}],对应配置", dataSourceName);
        List<Map<String, Object>> maps = null;
        try {
            DruidDataSource druidDataSource = new DruidDataSource();
            druidDataSource.setUrl(ruleDataSource.getUrl());
            druidDataSource.setUsername(ruleDataSource.getUsername());
            //解密 密码
            //DES des = SecureUtil.des(CommConstant.SECURE_KEY.getBytes());
            druidDataSource.setPassword(ruleDataSource.getPassword());
            DynamicDataSource.dataSourcesMap.put(dataSourceName, druidDataSource);
            // 源数据
            String source = DynamicDataSource.getDataSource();
            // 修改数据源
            DynamicDataSource.setDataSource(dataSourceName);
            //   此时数据源已切换到druidDataSource ，调用自己的业务方法即可。

            if (args[0] instanceof Map) {
                maps = ruleExecuteMapper.selectByMap(sqlStr, (Map<String, Object>) args[0]);
            } else {
                maps = ruleExecuteMapper.select(sqlStr, args);
            }

            //TODO: 2022年1月25日 如果数据为空则返回NULL

            // 还原数据源
            DynamicDataSource.setDataSource(source);
            DynamicDataSource.clear();

        } catch (Exception e) {
            e.printStackTrace();
            log.info("【数据源错误】 请检查sql 语句 或数据源配置 {}", e.getMessage());
            HibaseAssert.isTrue(false, "【数据源错误】 请检查sql 语句 或数据源配置 {}", e.getMessage());
        }

        if (null != maps && maps.size() == 1 && MapUtil.isEmpty(maps.get(0))) {
            return null;
        }
        return maps;
    }

//    @Override
//    public List<Map<String, Object>> executeSelectSqlDebug(String dataSourceName, String sqlStr ,Object... args)  {
//        Class cla = null;
//        try {
//            // 是否是多数据源
//            cla = Class.forName("com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder");
//            // 获取当前数据源Map
//            Map<String, DataSource> currentDataSources = dynamicRoutingDataSource.getCurrentDataSources();
//            log.info("【规则数据源查询】 已存在数据源列表: {}",currentDataSources.keySet());
//            boolean isExist = currentDataSources.containsKey(dataSourceName);
//            log.info("【规则数据源查询】 当前指定使用数据源 : {} | 是否存在 : {}",dataSourceName,isExist);
//            if (!isExist){
//                // 不存在则，查询数据库获取连接属性，创建数据源
//                // step 1. 查询数据库内的数据源配置
//                RuleDataSource ruleDataSource = ruleDataSourceService.getOne(new QueryWrapper<RuleDataSource>().eq("poll_name", dataSourceName));
//                DataSourceProperty dataSourceProperty = new DataSourceProperty();
//                BeanUtils.copyProperties(ruleDataSource,dataSourceProperty);
//
//                // step 2. 创建连接 添加到数据源 维护
//                DataSource dataSource = dynamicDataSourceCreator.createDataSource(dataSourceProperty);
//                dynamicRoutingDataSource.addDataSource(dataSourceName,dataSource);
//
//                log.info("【规则数据源查询】 创建新的数据库连接 : {}",ruleDataSource);
//
//            }
//            if (cla != null) {
////                Method setDataSourceLookupKey = cla.getMethod("setDataSourceLookupKey", new Class[]{String.class});   // 2.4.2 版本
//                Method setDataSourceLookupKey = cla.getMethod("push", new Class[]{String.class}); // 3.1.0 版本
//                // 设置数据源
//                setDataSourceLookupKey.invoke(null, dataSourceName);
//            }
//            // 执行业务查询操作
//            return  ruleExecuteMapper.selectDebug(sqlStr,args);
//        }catch (Exception e){
//            e.printStackTrace();
//            throw new BusinessException("【数据源错误】 请检查sql 语句 或数据源配置 :"+ e.getMessage());
//        }finally {
//            if (cla != null) {
//                Method clearDataSourceLookupKey = null;
//                try {
//                // 清除数据源
//                    // 清除数据源
//                    dynamicRoutingDataSource.removeDataSource(dataSourceName);
//                    clearDataSourceLookupKey = cla.getMethod("clear");
//                    clearDataSourceLookupKey.invoke(null);
//                } catch (NoSuchMethodException e1) {
//                    e1.printStackTrace();
//                } catch (IllegalAccessException e1) {
//                    e1.printStackTrace();
//                } catch (InvocationTargetException e1) {
//                    e1.printStackTrace();
//                }
//            }
//        }
//    }
//
/*
    @Override
    public List<Map<String, Object>> executeSelectSql(String dataSourceName, String sqlStr ,Object... args)  {
        Class cla = null;
        try {
            // 是否是多数据源
            cla = Class.forName("com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder");

            // 获取当前数据源Map
            Map<String, DataSource> currentDataSources = dynamicRoutingDataSource.getCurrentDataSources();
            log.info("【规则数据源查询】 已存在数据源列表: {}",currentDataSources.keySet());
            boolean isExist = currentDataSources.containsKey(dataSourceName);
            log.info("【规则数据源查询】 当前指定使用数据源 : {} | 是否存在 : {}",dataSourceName,isExist);

            if (!isExist){
                // 不存在则，查询数据库获取连接属性，创建数据源

                // step 1. 查询数据库内的数据源配置
                RuleDataSource ruleDataSource = ruleDataSourceService.getOne(new QueryWrapper<RuleDataSource>().eq("poll_name", dataSourceName));
                DataSourceProperty dataSourceProperty = new DataSourceProperty();
                BeanUtils.copyProperties(ruleDataSource,dataSourceProperty);

                // step 2. 创建连接 添加到数据源 维护
                DataSource dataSource = dynamicDataSourceCreator.createDataSource(dataSourceProperty);
                dynamicRoutingDataSource.addDataSource(dataSourceName,dataSource);

                log.info("【规则数据源查询】 创建新的数据库连接 : {}",ruleDataSource);

            }

            if (cla != null) {
//                Method setDataSourceLookupKey = cla.getMethod("setDataSourceLookupKey", new Class[]{String.class});
                Method setDataSourceLookupKey = cla.getMethod("push", new Class[]{String.class});
                // 设置数据源
                setDataSourceLookupKey.invoke(null, dataSourceName);
            }

            // 执行业务查询操作
            return  ruleExecuteMapper.select(sqlStr,args);

        }catch (Exception e){
            e.printStackTrace();
            throw new BusinessException("【数据源错误】 请检查sql 语句 或数据源配置 :"+ e.getMessage());
        }finally {
            if (cla != null) {
                Method clearDataSourceLookupKey = null;
                try {
                    // 清除数据源
                    dynamicRoutingDataSource.removeDataSource(dataSourceName);
                    clearDataSourceLookupKey = cla.getMethod("clear");
                    clearDataSourceLookupKey.invoke(null);
                } catch (NoSuchMethodException e1) {

                    e1.printStackTrace();
                } catch (IllegalAccessException e1) {
                    e1.printStackTrace();
                } catch (InvocationTargetException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }*/


    @Override
    public List<Map<String, Object>> getDataSet(String dataSetName, Object... args) {

        QueryWrapper<RuleMenuContent> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("type", "SOURCE");
        queryWrapper.eq("name", dataSetName);

        RuleMenuContent ruleMenuContent = ruleMenuContentService.getOne(queryWrapper);
        return this.executeSelectSql(ruleMenuContent.getDataSource(), ruleMenuContent.getContent(), args);

    }

    @Override
    public Object callRule(RuleCallParamVO paramVO) throws Exception {
        RuleMenuContent rule = ruleMenuContentService.getOne(new QueryWrapper<RuleMenuContent>().eq("name", paramVO.getRuleName()));
        HibaseAssert.notNull(rule, "规则不存在");
        HibaseAssert.isTrue(RuleStatus.RULE_STATUS_RELEASE.getKey().equals(rule.getStatus()),
                "规则未发布!");
        RuleExecuteParamVO executeParamVO = new RuleExecuteParamVO();
        executeParamVO.setId(rule.getId());
        executeParamVO.setData(paramVO.getRuleParam());
        return executeRule(executeParamVO);
    }

    @Override
    public Object callRule(String ruleName, Map<String, Object> paramMap) throws Exception {
        RuleMenuContent content = ruleMenuContentService.getOne(new QueryWrapper<RuleMenuContent>().eq("name", ruleName));
        HibaseAssert.notNull(content, "规则不存在");
        HibaseAssert.isTrue(RuleStatus.RULE_STATUS_RELEASE.getKey().equals(content.getStatus()),
                "规则未发布!");
//        RuleExecuteParamVO executeParamVO = new RuleExecuteParamVO();
//        executeParamVO.setId(rule.getId());
//        executeParamVO.setData(JSON.toJSONString(paramMap));
        return executeRule(content, paramMap);
    }

    /**
     * 子规则调用
     *
     * @param ruleName
     * @param map
     * @return
     */
    @Override
    public Object callChildRule(String ruleName, Map<String, Object> map) throws Exception {
        RuleMenuContent content = ruleMenuContentService.getOne(new QueryWrapper<RuleMenuContent>().eq("name", ruleName));
        HibaseAssert.notNull(content, "规则不存在");
//        RuleExecuteParamVO executeParamVO = new RuleExecuteParamVO();
//        executeParamVO.setId(rule.getId());
//        executeParamVO.setData(JSON.toJSONString(object));
        return executeChildRule(content, map);
    }


    private Object executeChildRule(RuleExecuteParamVO paramVO) throws Exception {
        RuleMenuContent ruleMenuContent = ruleMenuContentService.getById(paramVO.getId());
        HibaseAssert.notNull(ruleMenuContent, "请选择记录");
        HibaseAssert.isTrue(ruleMenuContent.getType().equals(RuleType.RULE_TYPE_RULE.getName()), "请选择正确的规则");

        DefaultContext<String, Object> paramContext = new DefaultContext<>();
        // 参数解析
        if (StrUtil.isNotBlank(paramVO.getData())) {
            // 解析json
            paramContext.put("参数", JSON.parseObject(paramVO.getData()).getInnerMap());
            paramContext.putAll(JSON.parseObject(paramVO.getData()).getInnerMap());
        }

        return hibaseRuleEngineUtils.executeChildExpress(ruleMenuContent, paramContext);

    }

    private Object executeChildRule(RuleMenuContent content, Map<String, Object> map) throws Exception {
        HibaseAssert.isTrue(content.getType().equals(RuleType.RULE_TYPE_RULE.getName()), "请选择正确的规则");
        DefaultContext<String, Object> paramContext = new DefaultContext<>();
        paramContext.putAll(map);
        return hibaseRuleEngineUtils.executeChildExpress(content, paramContext);
    }

    /**
     * 查询规则表
     *
     * @param ruleName 规则表数据
     * @param objects  查找项 + 时间 或者 查找项 + 范围查找项 + 时间
     * @return
     */
    @Override
    public List<Object> getRuleData(String ruleName, Object[] objects) {
        List<Object> result = new ArrayList<>();
        HibaseAssert.isTrue(ObjectUtil.isNotEmpty(objects), "参数不能为空!");
        long date = (Long) objects[objects.length - 1];
        Date versionDate = new Date(date);
        // 范围查询值
        BigDecimal rangeValue = null;
        // step 01 通过ruleName 查找规则表数据
        RuleTable table = ruleTableService.getOne(new QueryWrapper<RuleTable>()
                .eq("name", ruleName));
        HibaseAssert.notNull(table, "规则表不存在!");
        RuleTableVersion version = ruleTableVersionService.getOne(new QueryWrapper<RuleTableVersion>()
                .eq("rule_table_id", table.getId())
                .le("start_date", versionDate)
                .ge("end_date", versionDate)
        );
        HibaseAssert.notNull(version, "规则版本表不存在!");
        HibaseAssert.isTrue(RuleStatus.RULE_STATUS_RELEASE.getKey().equals(version.getStatus()), "规则版本表未发布!");
        List<RuleTableField> fieldList = ruleTableFieldService.list(new QueryWrapper<RuleTableField>()
                .eq("rule_table_id", version.getRuleTableId())
                .eq("filed_type", RuleFieldType.QUERY.getKey())
                .orderByAsc("column_sort"));
        HibaseAssert.isTrue(CollUtil.isNotEmpty(fieldList), "规则表中的查找项不存在!");
        Map<String, Object> map = new LinkedHashMap<>();
        // 生成查找项json
        if (table.getBeFindRange()) {
            HibaseAssert.isTrue(fieldList.size() + 2 == objects.length, "请检查查询参数,参数个数不对!");
            for (int i = 0; i < fieldList.size(); i++) {
                map.put(fieldList.get(i).getFieldName(), objects[i]);
            }
            //加入 范围查找项
            rangeValue = new BigDecimal(Long.parseLong(objects[objects.length - 2] + ""));
            HibaseAssert.notNull(rangeValue, "请检查参数,范围查找格式不正确,必须为数字类型!");
        } else {
            HibaseAssert.isTrue(fieldList.size() + 1 == objects.length, "请检查查询参数,参数个数不对!");
            for (int i = 0; i < fieldList.size(); i++) {
                map.put(fieldList.get(i).getFieldName(), objects[i]);
            }
        }
        String findJson = JSON.toJSONString(map);
        // step 02 生成hash
        String hash = RuleUtils.getHash(table.getName(), version.getName(), findJson);
        // step 03 查找redis
        String key = RuleUtils.getKey(table.getName(), version.getName(), findJson, hash);
        // 如果是范围查找那就是sortSet
        if (table.getBeFindRange()) {
            Set<ZSetOperations.TypedTuple<Object>> tupleSet = redisUtil.zRangeByScoreWithScores(key, rangeValue.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN).doubleValue(), Double.MAX_VALUE);
            Optional<ZSetOperations.TypedTuple<Object>> valueRange = tupleSet.stream().findFirst();
//            RScoredSortedSet<Object> rSet = redissonClient.getScoredSortedSet(key);
//            Optional<Object> valueRange = rSet.valueRange(rangeValue.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN).doubleValue(), true, Double.MAX_VALUE, false)
//                    .stream()
//                    .findFirst();
            if (valueRange.isPresent()) {
                result.addAll((List<Object>) valueRange.get());
            }
        } else {
//            RList<Object> list = redissonClient.getList(key);
            List<Object> list = redisUtil.lRange(key, 0, -1);
            result.addAll(list);
        }
        return result;
    }

    /**
     * 规则表数据
     * 时间 +查找项
     *
     * @param ruleName
     * @param objects
     * @return
     */
    @Override
    public List<Object> getRuleData2(String ruleName, Object[] objects) {
        List<Object> result = new ArrayList<>();
        HibaseAssert.isTrue(ObjectUtil.isNotEmpty(objects), "参数不能为空!");
        // 时间
        long date = (Long) objects[0];
        Date versionDate = new Date(date);
        // 范围查询值
        BigDecimal rangeValue = null;
        // step 01 通过ruleName 查找规则表数据
        RuleTable table = ruleTableService.getOne(new QueryWrapper<RuleTable>()
                .eq("name", ruleName));
        HibaseAssert.notNull(table, "规则表不存在!");
        RuleTableVersion version = ruleTableVersionService.getOne(new QueryWrapper<RuleTableVersion>()
                .eq("rule_table_id", table.getId())
                .le("start_date", versionDate)
                .ge("end_date", versionDate)
        );
        HibaseAssert.notNull(version, "规则版本表不存在!");
        HibaseAssert.isTrue(RuleStatus.RULE_STATUS_RELEASE.getKey().equals(version.getStatus()), "规则版本表未发布!");
        List<RuleTableField> fieldList = ruleTableFieldService.list(new QueryWrapper<RuleTableField>()
                .eq("rule_table_id", version.getRuleTableId())
                .eq("filed_type", RuleFieldType.QUERY.getKey())
                .orderByAsc("column_sort"));
        HibaseAssert.isTrue(CollUtil.isNotEmpty(fieldList), "规则表中的查找项不存在!");
        Map<String, Object> map = new LinkedHashMap<>();
        // 生成查找项json
        if (table.getBeFindRange()) {
            HibaseAssert.isTrue(fieldList.size() + 2 == objects.length, "请检查查询参数,参数个数不对!");
            for (int i = 0; i < fieldList.size(); i++) {
                map.put(fieldList.get(i).getFieldName(), objects[i + 1]);
            }
            //加入 范围查找项
            rangeValue = new BigDecimal(Long.parseLong(objects[objects.length - 1] + ""));
            HibaseAssert.notNull(rangeValue, "请检查参数,范围查找格式不正确,必须为数字类型!");
        } else {
            HibaseAssert.isTrue(fieldList.size() + 1 == objects.length, "请检查查询参数,参数个数不对!");
            for (int i = 0; i < fieldList.size(); i++) {
                map.put(fieldList.get(i).getFieldName(), objects[i + 1]);
            }
        }
        String findJson = JSON.toJSONString(map);
        // step 02 生成hash
        String hash = RuleUtils.getHash(table.getName(), version.getName(), findJson);
        // step 03 查找redis
        String key = RuleUtils.getKey(table.getName(), version.getName(), findJson, hash);
        // 如果是范围查找那就是sortSet
        if (table.getBeFindRange()) {
            Set<ZSetOperations.TypedTuple<Object>> tupleSet = redisUtil.zRangeByScoreWithScores(key, rangeValue.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN).doubleValue(), Double.MAX_VALUE);
            Optional<ZSetOperations.TypedTuple<Object>> valueRange = tupleSet.stream().findFirst();
//            RScoredSortedSet<Object> rSet = redissonClient.getScoredSortedSet(key);
//            Optional<Object> valueRange = rSet.valueRange(rangeValue.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN).doubleValue(), true, Double.MAX_VALUE, false)
//                    .stream()
//                    .findFirst();
            if (valueRange.isPresent()) {
                result.addAll((List<Object>) valueRange.get());
            }
        } else {
            List<Object> list = redisUtil.lRange(key, 0, -1);
//            RList<Object> list = redissonClient.getList(key);
            result.addAll(list);
        }
        return result;
    }

    @Override
    public List<Map<String, String>> getRuleData3(String ruleName, Object time, Object[] objects) {
        List<Map<String, String>> mapList = new ArrayList<>();
        List<Object> result = new ArrayList<>();
        HibaseAssert.isTrue(ObjectUtil.isNotEmpty(objects), "参数不能为空!");
        // step01 时间
        Date date = null;
        if (time instanceof String) {
            date = DateUtil.parse((String) time);
        } else if (time instanceof Date) {
            date = (Date) time;
        }
        // step02 通过ruleName 查找规则表数据
        // 范围查询值
        BigDecimal rangeValue = null;
        // step 01 通过ruleName 查找规则表数据
        RuleTable table = ruleTableService.getOne(new QueryWrapper<RuleTable>()
                .eq("name", ruleName));
        HibaseAssert.notNull(table, "规则表不存在!");
        HibaseAssert.isTrue(StrUtil.equals(table.getStatus(), RuleStatus.RULE_STATUS_RELEASE.getKey()), "{}规则表未启用", table.getName());
        RuleTableVersion version = ruleTableVersionService.getOne(new QueryWrapper<RuleTableVersion>()
                .eq("rule_table_id", table.getId())
                .le("start_date", date)
                .ge("end_date", date)
        );
        HibaseAssert.notNull(version, "规则版本表不存在!");
        HibaseAssert.isTrue(RuleStatus.RULE_STATUS_RELEASE.getKey().equals(version.getStatus()), "规则版本表未发布!");
        List<RuleTableField> fieldList = ruleTableFieldService.list(new QueryWrapper<RuleTableField>()
                .eq("rule_table_id", version.getRuleTableId())
                .eq("filed_type", RuleFieldType.QUERY.getKey())
                .orderByAsc("column_sort"));
        HibaseAssert.isTrue(CollUtil.isNotEmpty(fieldList), "规则表中的查找项不存在!");
        Map<String, Object> map = new LinkedHashMap<>();
        // 生成查找项json
        if (table.getBeFindRange()) {
            HibaseAssert.isTrue(fieldList.size() + 1 == objects.length, "请检查查询参数,参数个数不对!");
            for (int i = 0; i < fieldList.size(); i++) {
                map.put(fieldList.get(i).getFieldName(), objects[i]);
            }
            //加入 范围查找项
            rangeValue = new BigDecimal(objects[objects.length - 1].toString());
            HibaseAssert.notNull(rangeValue, "请检查参数,范围查找格式不正确,必须为数字类型!");
        } else {
            HibaseAssert.isTrue(fieldList.size() == objects.length, "请检查查询参数,参数个数不对!");
            for (int i = 0; i < fieldList.size(); i++) {
                map.put(fieldList.get(i).getFieldName(), objects[i]);
            }
        }
        String findJson = JSON.toJSONString(map);
        // step 02 生成hash
        String hash = RuleUtils.getHash(table.getName(), version.getName(), findJson);
        // step 03 查找redis
        String key = RuleUtils.getKey(table.getName(), version.getName(), findJson, hash);
        // 如果是范围查找那就是sortSet
        if (table.getBeFindRange()) {
            Set<ZSetOperations.TypedTuple<Object>> tupleSet = redisUtil.zRangeByScoreWithScores(key, rangeValue.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN).doubleValue(), Double.MAX_VALUE);
            Optional<ZSetOperations.TypedTuple<Object>> valueRange = tupleSet.stream().findFirst();
//            RScoredSortedSet<Object> rSet = redissonClient.getScoredSortedSet(key);
//            Optional<Object> valueRange = rSet.valueRange(rangeValue.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN).doubleValue(), true, Double.MAX_VALUE, false)
//                    .stream()
//                    .findFirst();
            if (valueRange.isPresent()) {
                result.addAll((List<Object>) valueRange.get());
            }
        } else {
            List<Object> list = redisUtil.lRange(key, 0, -1);
//            RList<Object> list = redissonClient.getList(key);
            result.addAll(list);
        }
        // string 转 map
        if (CollUtil.isNotEmpty(result)) {
            result.forEach(json -> {
                HashMap<String, String> hashMap = new HashMap<>();
                JSONObject jsonObject = JSONUtil.parseObj(json);
                for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
                    hashMap.put(entry.getKey(), entry.getValue().toString());
                }
                mapList.add(hashMap);
            });
            //多值排序
            if (table.getBeMultiValue()) {
                return mapList.stream().sorted((data1, data2) -> {
                    String priority1 = data1.get("priority");
                    String priority2 = data2.get("priority");
                    if (Integer.parseInt(priority1) == Integer.parseInt(priority2)) {
                        return 0;
                    }
                    return Integer.parseInt(priority1) > Integer.parseInt(priority2) ? -1 : 1;
                }).collect(Collectors.toList());
            }
        }

        return mapList;
    }

    /**
     * 规则表唯一值
     *
     * @param ruleName
     * @param objects
     * @return
     */
    @Override
    public Map getOneRuleData(String ruleName, Object time, Object[] objects) {
        HashMap<String, String> result = new HashMap<>();
        RuleTable table = ruleTableService.getOne(new QueryWrapper<RuleTable>()
                .eq("name", ruleName));
        HibaseAssert.notNull(table, "规则表不存在!");
        HibaseAssert.isFalse(table.getBeMultiValue(), "动态表唯一值不支持多值");
        List<Map<String, String>> ruleData = getRuleData3(ruleName, time, objects);
        if (CollUtil.isNotEmpty(ruleData)) {
            Map<String, String> map = ruleData.get(0);
            result.putAll(map);
        }
        return result;
    }

    /**
     * 优先级排序
     *
     * @param ruleName
     * @param objects
     * @return
     */
    @Override
    public List<Map<String, String>> getPriorityRuleData(String ruleName, Object[] objects) {
        RuleTable table = ruleTableService.getOne(new QueryWrapper<RuleTable>()
                .eq("name", ruleName));
        HibaseAssert.notNull(table, "规则表不存在!");
        HibaseAssert.isTrue(table.getBeMultiValue(), "动态表优先级不支持单一值");
        List<Map<String, String>> dataResult = getRuleDataResult(ruleName, objects);
        //有限制字段固定 排序
        dataResult = dataResult.stream().sorted((data1, data2) -> {
            String priority1 = data1.get("priority");
            String priority2 = data2.get("priority");
            if (Integer.parseInt(priority1) == Integer.parseInt(priority2)) {
                return 0;
            }
            return Integer.parseInt(priority1) > Integer.parseInt(priority2) ? -1 : 1;
        }).collect(Collectors.toList());
        return dataResult;
    }

    /**
     * 查询动态表升级版  兼容查询动态表
     * 规则表 json 转 map
     *
     * @param ruleName
     * @param objects
     * @return
     */
    @Override
    public List<Map<String, String>> getRuleDataResult(String ruleName, Object[] objects) {
        List<Map<String, String>> result = new ArrayList<>();
        RuleTable table = ruleTableService.getOne(new QueryWrapper<RuleTable>()
                .eq("name", ruleName));
        HibaseAssert.notNull(table, "规则表不存在!");
        List<Object> ruleData = getRuleData2(ruleName, objects);
        if (CollUtil.isNotEmpty(ruleData)) {
            ruleData.forEach(json -> {
                HashMap<String, String> map = new HashMap<>();
                JSONObject jsonObject = JSONUtil.parseObj(json);
                for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
                    map.put(entry.getKey(), entry.getValue().toString());
                }
                result.add(map);
            });
            if (table.getBeMultiValue()) {
                return result.stream().sorted((data1, data2) -> {
                    String priority1 = data1.get("priority");
                    String priority2 = data2.get("priority");
                    if (Integer.parseInt(priority1) == Integer.parseInt(priority2)) {
                        return 0;
                    }
                    return Integer.parseInt(priority1) > Integer.parseInt(priority2) ? -1 : 1;
                }).collect(Collectors.toList());
            }
        }
        return result;
    }

    /**
     * 查询规则信息
     *
     * @param ruleId
     * @return
     */
    private RuleMenuContent getRuleMenuContent(String ruleId) {
        RuleMenuContent ruleMenuContent = ruleMenuContentService.getById(ruleId);
        HibaseAssert.notNull(ruleMenuContent, "请选择记录");
        HibaseAssert.isTrue(RuleStatus.RULE_STATUS_RELEASE.getKey().equals(ruleMenuContent.getStatus()),
                "规则未发布!");
        return ruleMenuContent;
    }
}
